package socketmvc.client.context;

import socketmvc.client.session.SocketCliSession;
import socketmvc.core.config.SocketMvcConfig;
import socketmvc.core.context.IContext;
import socketmvc.core.packets.ResponseFuture;
import socketmvc.core.packets.basic.IPacket;
import socketmvc.core.util.PacketHandler;
import socketmvc.core.util.StringUtils;
import java.util.HashMap;
import java.util.Map;

public class SocketChannel implements IContext {

    Map<String,Object> attrs = new HashMap<>();

    SocketCliSession target;

    PacketHandler packetHandler;

    IPacket packet;

    SocketMvcConfig.IpConfig serverIpConfig;

    public SocketChannel(SocketCliSession target, PacketHandler packetHandler) {
        this.target = target;
        this.packetHandler = packetHandler;
    }

    public void setPacket(IPacket packet) {
        this.packet = packet;
    }

    public void setServerIpConfig(SocketMvcConfig.IpConfig serverIpConfig) {
        this.serverIpConfig = serverIpConfig;
    }

    /**
     * 当前数据包
     * 当接受到客户端的数据包之后，该函数返回的就是当前接受到的数据包
     *
     * @return packet
     */
    @Override
    public IPacket getPacket() {
        return packet;
    }

    /**
     * 获取附加值
     *
     * @param key k
     * @return v
     */
    @Override
    public Object getAttr(String key) {
        return attrs.get(key);
    }

    /**
     * 设置附加值
     *
     * @param key k
     * @param val v
     * @return v
     */
    @Override
    public Object setAttr(String key, Object val) {
        return attrs.put(key,val);
    }

    /**
     * 删除附加值
     *
     * @param key k
     * @return 被删除的值
     */
    @Override
    public Object removeAttr(String key) {
        return attrs.remove(key);
    }

    /**
     * tcp,udp,ws
     *
     * @return 连接的类型
     */
    @Override
    public String getType() {
        return getClientConnInfo().getType().getName();
    }

    /**
     * 发送数据包到当前context
     *
     * @param packet 数据包
     */
    @Override
    public void send(IPacket packet) {
        target.send(packetHandler.toByteBuffer(wrapPacket(packet)));
    }

    /**
     * 发送数据包到当前context,并等待响应结果
     *
     * @param packet 数据包
     * @return 等待结果
     */
    @Override
    public ResponseFuture sendSync(IPacket packet) {
        ResponseFuture responseFuture = (ResponseFuture) IContext.super.createResponseFuture(packet);
        this.send(packet);
        return responseFuture;
    }

    /**
     * 发送响应包
     * @param response
     */
    public void response(IPacket response) {
        IPacket packet = this.getThreadPacket();
        if (packet != null) {
            response.setCommand(packet.getCommand());
            response.setResponseKey(packet.getResponseKey());
            response.setResponsePkt(true);
        }
        target.send(packetHandler.toByteBuffer(response));
    }

    /**
     * 关闭当前context
     * 注意：关闭意味着彻底抛弃链接，关闭后就不能再发送消息了
     */
    @Override
    public void close() {
        target.close();
    }

    /**
     * 获取客户端host信息
     *
     * @return 客户端host信息
     */
    @Override
    public SocketMvcConfig.IpConfig getClientConnInfo() {
        return null;
    }

    /**
     * 获取服务端host信息
     *
     * @return 服务端host信息
     */
    @Override
    public SocketMvcConfig.IpConfig getServerConnInfo() {
        return serverIpConfig;
    }

    public SocketCliSession getTarget() {
        return target;
    }

    private IPacket wrapPacket(IPacket packet){
        if (packet == null){
            return null;
        }
        // 当前要发送的数据包中未标识cmd命令码的情况下
        if (StringUtils.isEmpty(packet.getCommand())){
            IPacket threadPacket = getThreadPacket();
            if (threadPacket != null){
                packet.setCommand(threadPacket.getCommand());
            }
        }
        return packet;
    }

    private IPacket getThreadPacket(){
        if (this.packet == null){
            SocketChannel threadCxt = ThreadSocketChannelHandler.get();
            if (threadCxt != null){
                return threadCxt.getThreadPacket();
            }
        }
        return this.packet;
    }
}
